module Mutant
  module AST
    # Groups of node types
    #
    # :reek:TooManyConstants
    # rubocop:disable Metrics/ModuleLength
    module Types
      symbolset = ->(strings) { strings.map(&:to_sym).to_set.freeze }

      ASSIGNABLE_VARIABLES = symbolset.(%w[ivasgn lvasgn cvasgn gvasgn])

      INDEX_ASSIGN_OPERATOR = :[]=

      # Set of nodes that cannot be on the LHS of an assignment
      NOT_ASSIGNABLE         = symbolset.(%w[int float str dstr class module self nil])

      # Set of op-assign types
      OP_ASSIGN              = symbolset.(%w[or_asgn and_asgn op_asgn])
      # Set of node types that are not valid when emitted standalone
      NOT_STANDALONE         = symbolset.(%w[splat restarg block_pass])
      INDEX_OPERATORS        = symbolset.(%w[[] []=])
      UNARY_METHOD_OPERATORS = symbolset.(%w[~@ +@ -@ !])

      # Operators ruby implements as methods
      METHOD_OPERATORS = symbolset.(%w[
        <=> === []= [] <= >= == !~ != =~ <<
        >> ** * % / | ^ & < > + - ~@ +@ -@ !
      ])

      BINARY_METHOD_OPERATORS = symbolset.(
        METHOD_OPERATORS - (INDEX_OPERATORS + UNARY_METHOD_OPERATORS)
      )

      OPERATOR_METHODS = symbolset.(
        METHOD_OPERATORS + INDEX_OPERATORS + UNARY_METHOD_OPERATORS
      )

      # Nodes that are NOT handled by mutant.
      #
      # not - 1.8 only, mutant does not support 1.8
      #
      BLACKLIST = symbolset.(%w[not])

      # Nodes generated by regular expression body parsing
      REGEXP = symbolset.(%w[
        regexp_alpha_property
        regexp_alternation_escape
        regexp_alternation_meta
        regexp_atomic_group
        regexp_backslash_escape
        regexp_bell_escape
        regexp_bol_anchor
        regexp_bos_anchor
        regexp_capture_group
        regexp_carriage_escape
        regexp_character_set
        regexp_character_set
        regexp_codepoint_list_escape
        regexp_comment_free_space
        regexp_comment_group
        regexp_control_escape
        regexp_digit_type
        regexp_dot_escape
        regexp_dot_meta
        regexp_eol_anchor
        regexp_eol_escape
        regexp_eos_anchor
        regexp_eos_ob_eol_anchor
        regexp_escape_escape
        regexp_form_feed_escape
        regexp_greedy_interval
        regexp_greedy_one_or_more
        regexp_greedy_zero_or_more
        regexp_greedy_zero_or_one
        regexp_group_close_escape
        regexp_group_open_escape
        regexp_hex_escape
        regexp_hex_type
        regexp_interval_close_escape
        regexp_interval_open_escape
        regexp_letter_any_property
        regexp_literal_escape
        regexp_literal_literal
        regexp_lookahead_assertion
        regexp_lookbehind_assertion
        regexp_mark_keep
        regexp_match_start_anchor
        regexp_meta_sequence_escape
        regexp_name_call_backref
        regexp_named_group
        regexp_newline_escape
        regexp_nlookahead_assertion
        regexp_nlookbehind_assertion
        regexp_nondigit_type
        regexp_nonspace_type
        regexp_nonword_boundary_anchor
        regexp_nonword_type
        regexp_nonhex_type
        regexp_number_backref
        regexp_one_or_more_escape
        regexp_open_conditional
        regexp_options_group
        regexp_passive_group
        regexp_possessive_interval
        regexp_possessive_one_or_more
        regexp_possessive_zero_or_more
        regexp_possessive_zero_or_one
        regexp_reluctant_interval
        regexp_reluctant_one_or_more
        regexp_reluctant_zero_or_more
        regexp_root_expression
        regexp_script_arabic_property
        regexp_script_han_property
        regexp_script_hangul_property
        regexp_script_hiragana_property
        regexp_script_katakana_property
        regexp_sequence_expression
        regexp_set_close_escape
        regexp_set_open_escape
        regexp_space_type
        regexp_tab_escape
        regexp_vertical_tab_escape
        regexp_whitespace_free_space
        regexp_word_boundary_anchor
        regexp_word_type
        regexp_zero_or_more_escape
        regexp_zero_or_one_escape
      ])

      # Nodes that are NOT generated by parser but used by mutant / unparser.
      GENERATED = symbolset.(%w[empty])

      EXTRA = symbolset.(GENERATED + REGEXP)

      # All node types mutant handles
      ALL = symbolset.((Parser::Meta::NODE_TYPES + EXTRA) - BLACKLIST)
    end # Types
  end # AST
end # Mutant
